package com.smedi.ismedi.organization.core.application.query.impl;

import com.smedi.ismedi.organization.core.application.command.ProjectOrganizationListQueryCommand;
import com.smedi.ismedi.organization.core.application.convert.AppConverter;
import com.smedi.ismedi.organization.core.application.query.ProjectOrganizationQueryService;
import com.smedi.ismedi.organization.core.application.query.vo.ProjectOrganizationVo;
import com.smedi.ismedi.organization.core.domain.aggregatemodel.ProjectOrganization;
import com.smedi.ismedi.organization.core.domain.aggregatemodel.dto.ProjectOrganizationQuery;
import com.smedi.ismedi.organization.core.domain.aggregatemodel.model.ProjectOrganizationModel;
import com.smedi.ismedi.organization.core.domain.repository.ProjectOrganizationRepository;
import com.smedi.ismedi.organization.core.domain.service.ProjectOrganizationDomainService;
import com.smedi.ismedi.organization.core.infrastructure.constant.CustomError;
import com.smedi.ismedi.organization.core.infrastructure.enumerate.ProjectOrganizationTypeEnum;
import com.smedi.ismedi.organization.core.infrastructure.enumerate.SpecialTypeEnum;
import com.smedi.ismedi.web.starter.exception.LogicException;
import com.smedi.ismedi.web.starter.util.DozerUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@AllArgsConstructor
public class ProjectOrganizationQueryServiceImpl implements ProjectOrganizationQueryService {
    private final ProjectOrganizationDomainService projectOrganizationDomainService;

    private final ProjectOrganizationRepository projectOrganizationRepository;

    private final DozerUtil dozerUtil;

    private final AppConverter appConverter;

    /**
     * 项目组织转换
     *
     * @param modal
     * @return
     */
    private ProjectOrganizationVo projectOrganizationToVo(ProjectOrganization modal) {
        ProjectOrganizationVo vo = dozerUtil.convertor(modal, ProjectOrganizationVo.class);
        // 组织类型
        vo.setTypeMeaning(ProjectOrganizationTypeEnum.getName(modal.getType()));
        // 特性信息
        vo.setSpecialTypeMeaning(SpecialTypeEnum.getName(vo.getSpecialType()));
        // 子组织
        vo.setProjectOrganizationChildren(dozerUtil.convertor(projectOrganizationDomainService.getProjectOrganizationChildrenByTree(modal.getProjectOrganizationId()), ProjectOrganizationVo.class));
        return vo;
    }

    @Override
    public List<ProjectOrganizationVo> getProjectOrganizationTree(Long projectId) {
        List<ProjectOrganizationVo> list = new ArrayList<>();
        List<ProjectOrganization> roots = projectOrganizationRepository.selectAllRoots(projectId);
        for (ProjectOrganization i : roots) {
            list.add(projectOrganizationToVo(i));
        }
        return list;
    }

    @Override
    public List<ProjectOrganizationVo> getAllProjectOrganizationList() {
        List<ProjectOrganization> projectOrganizations = projectOrganizationRepository.queryAll();

        return dozerUtil.convertor(projectOrganizations, ProjectOrganizationVo.class);
    }

    @Override
    public ProjectOrganizationVo getProjectOrganizationView(Long projectOrganizationId) {
        ProjectOrganization projectOrganization = projectOrganizationRepository.selectByProjectOrganizationId(projectOrganizationId);
        if (projectOrganization != null) {
            return projectOrganizationToVo(projectOrganization);
        } else {
            throw LogicException.raise(CustomError.PROJECT_ORGANIZATION_NOT_EXIST);
        }
    }

    @Override
    public List<Long> getProjectOrganizationChildrenIdList(Long projectOrganizationId) {
        List<ProjectOrganization> list = projectOrganizationDomainService.getProjectOrganizationChildrenByList(projectOrganizationId);
        List<Long> arrayList = new ArrayList<>();
        for (ProjectOrganization projectOrganization : list) {
            arrayList.add(projectOrganization.getProjectOrganizationId());
        }
        if (!arrayList.contains(projectOrganizationId)) {
            arrayList.add(0, projectOrganizationId);
        }
        return arrayList;
    }

    @Override
    public Map<Long, String> getProjectOrganizationChildrenMap(Long projectOrganizationId) {
        List<ProjectOrganization> list = projectOrganizationDomainService.getProjectOrganizationChildrenByList(projectOrganizationId);
        ProjectOrganization basic = projectOrganizationRepository.selectByProjectOrganizationId(projectOrganizationId);
        Map<Long, String> maps = new HashMap<>();
        if (basic != null) {
            maps.put(basic.getProjectOrganizationId(), basic.getFullName());
        } else {
            return new HashMap<>();
        }

        for (ProjectOrganization projectOrganization : list) {
            if (!maps.containsKey(projectOrganization.getProjectOrganizationId())) {
                maps.put(projectOrganization.getProjectOrganizationId(), projectOrganization.getFullName());
            }
        }

        return maps;
    }

    @Override
    public List<ProjectOrganizationVo> getProjectOrganizationByProjectOrganizationIds(List<Long> projectOrganizationIds) {
        List<ProjectOrganizationVo> projectOrganizationVos = new ArrayList<>();
        for (Long projectOrganizationId : projectOrganizationIds) {
            ProjectOrganization projectOrganization = projectOrganizationRepository.selectByProjectOrganizationId(projectOrganizationId);
            ProjectOrganizationVo projectOrganizationVo = projectOrganizationToVo(projectOrganization);
            if (projectOrganizationVo != null) {
                projectOrganizationVos.add(projectOrganizationVo);
            }
        }
        return projectOrganizationVos;
    }

    /**
     * 领域转换成视图
     *
     * @param list
     * @return
     */
    private List<ProjectOrganizationVo> domainTransformToView(List<ProjectOrganization> list) {
        List<ProjectOrganizationVo> views = dozerUtil.convertor(list, ProjectOrganizationVo.class);

        views.stream().forEach(view -> {
            if (view.getParentId() != null) {
                ProjectOrganizationVo parent = getProjectOrganizationView(view.getParentId());
                view.setParentFullName(parent.getFullName());
                view.setParentShortName(parent.getShortName());
            }
        });

        return views;
    }

    @Override
    public List<ProjectOrganizationVo> queryProjectOrganizationListByFullName(String fullName, Long projectId) {
        List<ProjectOrganization> list = projectOrganizationRepository.selectAllByFullNameLikeAndProjectId(fullName, projectId);
        return domainTransformToView(list);
    }

    @Override
    public List<ProjectOrganizationVo> queryProjectOrganizationListByFullNameList(List<String> fullNameList) {
        List<ProjectOrganization> list = projectOrganizationRepository.selectAllByFullNameList(fullNameList);
        return dozerUtil.convertor(list, ProjectOrganizationVo.class);
    }

    @Override
    public List<ProjectOrganizationVo> queryProjectOrganizationListByProjectId(Long projectId) {
        List<ProjectOrganization> list = projectOrganizationRepository.selectAllByProjectId(projectId);
        return domainTransformToView(list);
    }

    @Override
    public List<Long> getParentProjectOrganizationIdsByProjectOrganizationId(Long projectOrganizationId) {
        ProjectOrganization projectOrganization = projectOrganizationRepository.selectByProjectOrganizationId(projectOrganizationId);
        List<Long> hrOrganizationIds = new ArrayList<>();

        if (projectOrganization != null) {
            if (projectOrganization.getParentId() != null) {
                hrOrganizationIds.add(projectOrganization.getParentId());
                hrOrganizationIds.addAll(getParentProjectOrganizationIdsByProjectOrganizationId(projectOrganization.getParentId()));
            }
        }

        return hrOrganizationIds;
    }

    @Override
    public List<ProjectOrganizationVo> getProjectOrganizationByProjectIdAndSpecialTypes(Long projectId, List<String> specialTypes) {
        return dozerUtil.convertor(projectOrganizationRepository.selectAllByProjectIdAndSpecialTypes(projectId, specialTypes), ProjectOrganizationVo.class);
    }

    @Override
    public List<ProjectOrganizationVo> queryProjectOrganizationsByProjectId(Long projectId) {
        List<String> specialTypes=new ArrayList<>();
        specialTypes.add("EXTERNAL_UNIT");
        List<ProjectOrganization> list = projectOrganizationRepository.selectAllByProjectIdAndSpecialTypes(projectId,specialTypes);

        return dozerUtil.convertor(list, ProjectOrganizationVo.class);
    }

    @Override
    public List<ProjectOrganizationModel> getProjectOrganizationList(ProjectOrganizationListQueryCommand projectOrganizationListQueryCommand) {
        ProjectOrganizationQuery projectOrganizationQuery = appConverter.projectOrganizationListQueryCommandToProjectOrganizationQuery(projectOrganizationListQueryCommand);
        return projectOrganizationRepository.getProjectOrganizationList(projectOrganizationQuery);
    }


}
